package birdsong.dummy;

import java.util.HashMap;
import java.util.LinkedList;

import birdsong.comm.ServerComm;
import birdsong.comm.ServerSideMessage;
import birdsong.server.BirdsongServer;

/**
 * 
 * @author João Gomes, Bernardo Coelho, Erick Echers, Pedro Túbal
 * <p>
 * This class makes all the server logic.
 * Keeps information about:
 * who is online - information stored in a {@link LinkedList};
 * who follow who - information stored in a {@link HashMap}.
 * 
 * The most important thing about server, is that it deals with all 5 types of {@link ServerSideMessage}, and sends the informations back 
 * to the users, using methods of {@link ServerComm}.
 *  
 */

public class BirdsongServerDummy implements BirdsongServer {

	private LinkedList<String> connected;
	private HashMap<String, LinkedList<String>> followers;
	private ServerSideMessage message;		//just to help

	/**
	 * This method makes the server run. It will not stop unless we force it.
	 * @param serverComm that's our link to recieve and send messages to clients
	 */
	@Override
	public void start(ServerComm serverComm) {

		System.out.println("Server is Starting...");
		connected = new LinkedList<String>();
		followers = new HashMap<String, LinkedList<String>>();

		System.out.println("The server has started!");

		while (true) {

			System.out.println("Searching for new messages...");

			if (serverComm.hasNextMessage()) {
				System.out.println("A new message has arrived");
				message = serverComm.getNextMessage();

				//Deal with the right type of message
				switch (message.getType()) {
				case BIRDSONG_MESSAGE:

					System.out.println("Dealing with birdsong message from  " + message.getClientNickname());
					
						//message for himself
						serverComm.sendBirdsongMessage(message.getClientNickname(), message.getClientNickname(),
								"You said: " + message.getPayload());

						//message for followers
						String str = message.getClientNickname() + " said: " + message.getPayload();
						for (String follower : followers.get(message.getClientNickname())) {
							serverComm.sendBirdsongMessage(message.getClientNickname(), follower, str);
					}

					System.out.println("Messages delivered!");

					break;
				case CLIENT_CONNECTED:

					System.out.println(message.getClientNickname() + " is trying to connect");

						//adding a new list of followers for the client
						followers.put(message.getClientNickname(), new LinkedList<String>());
						System.out.println("New follower list has been added to " + message.getClientNickname());

						//inform connected clients
						for (String user : connected) {
							serverComm.sendClientConnected(message.getClientNickname(), user);
							serverComm.sendClientConnected(user, message.getClientNickname());
						}

						//add client to connected people
						connected.add(message.getClientNickname());

					System.out.println("Client is now connected");

					break;
				case CLIENT_DISCONNECTED:

					System.out.println(message.getClientNickname() + " is trying to disconnect");

						//remove client from connected
						connected.remove(message.getClientNickname());

						//remove all followers of the client
						followers.remove(message.getClientNickname());
						
						//remove client followed
						for (String user : connected) {
							followers.get(user).remove(message.getClientNickname());
						}
						
						//inform connected clients
						for (String user: connected) {
							serverComm.sendClientDisconnected(user, message.getClientNickname());
						}

					System.out.println("Client is disconected");
					break;
				case FOLLOW:

					System.out.println(message.getClientNickname() + " wants to follow " + message.getPayload());

						//inform follow client
						if (connected.contains(message.getPayload())) {
							serverComm.sendNewFollower(message.getPayload(), message.getClientNickname());
							followers.get(message.getClientNickname()).add(message.getPayload());
						} else {
							serverComm.sendError(message.getClientNickname(), "There is no such client to follow");
						}

					System.out.println("Following successful");

					break;
				case UNFOLLOW:

					System.out.println(message.getClientNickname() + " wants to unfollow " + message.getPayload());

						//inform follow client
						if (connected.contains(message.getPayload())) {
							serverComm.sendNewUnfollow(message.getPayload(), message.getClientNickname());
							followers.get(message.getClientNickname()).remove(message.getPayload());
						} else {
							serverComm.sendError(message.getClientNickname(), "There is no such client to unfollow");
						}
					System.out.println("Unfollowing successful");

					break;
				default:
					serverComm.sendError(message.getClientNickname(), "Invalid type of message");
					break;
				}
			}
		}
	}

}